package com.snowj.apaas.service.impl;

import com.snowj.apaas.domain.auto.GroupMembers;
import com.snowj.apaas.domain.auto.UserGroups;
import com.snowj.apaas.domain.auto.Users;
import com.snowj.apaas.repository.auto.*;
import com.snowj.apaas.security.SecurityUtils;
import com.snowj.apaas.service.UsersService;
import com.snowj.apaas.web.vm.UsersVm;
import org.mybatis.dynamic.sql.where.condition.IsEqualTo;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author oliver
 * @date 2020/9/26
 */
@Service
public class UsersServicesImpl implements UsersService {

    private final UsersMapper usersMapper;

    private final GroupMembersMapper groupMembersMapper;

    private final UserGroupsMapper userGroupsMapper;

    private final BCryptPasswordEncoder passwordEncoder;

    public UsersServicesImpl(UsersMapper usersMapper, GroupMembersMapper groupMembersMapper, UserGroupsMapper userGroupsMapper, BCryptPasswordEncoder passwordEncoder) {
        this.usersMapper = usersMapper;
        this.groupMembersMapper = groupMembersMapper;
        this.userGroupsMapper = userGroupsMapper;
        this.passwordEncoder = passwordEncoder;
    }

    /**
     * 获取用户列表
     *
     * @param pageable
     * @return
     */
    @Override
    public Page<UsersVm> listUsers(Pageable pageable) {
        List<Users> list = usersMapper.select(c -> c.limit(pageable.getPageSize()));
        List<UsersVm> usersVmList = list.stream().map(users -> {
            users.setPassword(null);
            List<GroupMembers> groupMembers = groupMembersMapper
                    .select(c -> c.where(GroupMembersDynamicSqlSupport.username, IsEqualTo.of(users::getUsername)));
            List<Long> userGroups = groupMembers.stream()
                    .map(GroupMembers::getGroupId).collect(Collectors.toList());
            UsersVm usersVm = new UsersVm();
            BeanUtils.copyProperties(users, usersVm);
            usersVm.setUserGroupIds(userGroups);
            return usersVm;
        }).collect(Collectors.toList());
        long count = usersMapper.count(c -> c);
        return new PageImpl<>(usersVmList, pageable, count);
    }

    /**
     * 获取用户信息
     *
     * @param username
     * @return
     */
    @Override
    public Optional<UsersVm> getUserByUsername(String username) {
        return usersMapper.selectByPrimaryKey(username).map(users -> {
            users.setPassword(null);
            List<GroupMembers> groupMembers = groupMembersMapper
                    .select(c -> c.where(GroupMembersDynamicSqlSupport.username, IsEqualTo.of(users::getUsername)));
            List<Long> userGroups = groupMembers.stream()
                    .map(GroupMembers::getGroupId).collect(Collectors.toList());
            UsersVm usersVm = new UsersVm();
            BeanUtils.copyProperties(users, usersVm);
            usersVm.setUserGroupIds(userGroups);
            return usersVm;
        });
    }

    /**
     * 创建用户
     *
     * @param users
     * @return
     */
    @Override
    @Transactional
    public Users createUser(UsersVm users) {
        if (users.getUsername() == null) {
            return null;
        }
        users.setPassword(passwordEncoder.encode(users.getPassword()));
        users.setCreatedBy(SecurityUtils.getCurrentUserLogin());
        users.setCreatedDate(new Date());
        usersMapper.insert(users);

        // 删除用户组重新加入
        groupMembersMapper.delete(c -> c.where(GroupMembersDynamicSqlSupport.username, IsEqualTo.of(users::getUsername)));
        List<Long> userGroups = users.getUserGroupIds();
        List<GroupMembers> groupMembersList = userGroups.stream().map(groupId -> {
            GroupMembers groupMembers = new GroupMembers();
            groupMembers.setUsername(users.getUsername());
            groupMembers.setGroupId(groupId);
            return groupMembers;
        }).collect(Collectors.toList());
        groupMembersMapper.insertMultiple(groupMembersList);
        return users;
    }

    /**
     * 编辑用户
     *
     * @param users
     * @return
     */
    @Override
    @Transactional
    public Users updateUser(UsersVm users) {
        if (users.getUsername() == null) {
            return null;
        }
        Optional<Users> usersOptional = usersMapper.selectByPrimaryKey(users.getUsername());
        if (usersOptional.isPresent()) {
            Users savedUsers = usersOptional.get();
            users.setPassword(savedUsers.getPassword());
            users.setCreatedBy(savedUsers.getCreatedBy());
            users.setCreatedDate(savedUsers.getCreatedDate());
            users.setLastModifiedBy(SecurityUtils.getCurrentUserLogin());
            users.setLastModifiedDate(new Date());
            usersMapper.updateByPrimaryKey(users);

            // 删除用户组重新加入
            groupMembersMapper.delete(c -> c.where(GroupMembersDynamicSqlSupport.username, IsEqualTo.of(users::getUsername)));
            List<Long> userGroups = users.getUserGroupIds();
            List<GroupMembers> groupMembersList = userGroups.stream().map(groupId -> {
                GroupMembers groupMembers = new GroupMembers();
                groupMembers.setUsername(users.getUsername());
                groupMembers.setGroupId(groupId);
                return groupMembers;
            }).collect(Collectors.toList());
            groupMembersMapper.insertMultiple(groupMembersList);
            return users;
        }
        return null;
    }

    /**
     * 删除用户
     *
     * @param username
     */
    @Override
    public void deleteUser(String username) {
        // 删除用户组重新加入
        groupMembersMapper.delete(c -> c.where(GroupMembersDynamicSqlSupport.username, IsEqualTo.of(() -> username)));
        usersMapper.deleteByPrimaryKey(username);
    }
}
